package server;

import data.Persistence;
import data.dao.ContactsDaoApi;
import pojo.Contacts;

import java.awt.print.Book;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.*;

/**
 * @author mayanwei
 */
public class NioServer {

    public static final String USERNAME="admin";
    public static final String PASSWORD="123456";
    public static final String ISACK="ACK";
    public static final String ISNAK="NAK!";

    public static String serverIp = "127.0.0.1"; //服务器默认ip地址
    public static int serverPort = 8888;   //服务器默认端口

    // Selector selector;//选择器
    // SelectionKey key;//key。 一个key代表一个Selector 在NIO通道上的注册,类似主键;
    //取得这个Key后就可以对Selector在通道上进行操作

    private ByteBuffer echoBuffer = ByteBuffer.allocate( 1024 );// 通道数据缓冲区

    /**
     * 读取配置信息
     */
    public NioServer(){

        InputStream resource = this.getClass().getClassLoader().getResourceAsStream("application.properties");
        Properties p = new Properties();
        try{
            p.load(resource);
            System.out.println("serverIp:"+p.getProperty("serverIp")+";"+"serverPort:"+p.getProperty("serverPort"));

            this.serverIp = p.getProperty("serverIp");
            this.serverPort = Integer.parseInt(p.getProperty("serverPort"));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                resource.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public void BuildNioServer() throws IOException {

        /**
         *  先对服务端的ServerSocket进行注册,注册到Selector
         */

        ServerSocketChannel ssc = ServerSocketChannel.open();   //新建NIO通道
        ssc.configureBlocking( false );                         //使通道为非阻塞
        ServerSocket ss = ssc.socket();                         //创建基于NIO通道的socket连接

        ss.bind(new InetSocketAddress(serverIp,serverPort));    //新建socket通道的端口

        Selector selector=Selector.open();                      //获取一个选择器

        //将NIO通道选绑定到择器,当然绑定后分配的主键为skey
        SelectionKey skey = ssc.register( selector, SelectionKey.OP_ACCEPT );


        /**
         * 接收客户端的连接Socket,并将此Socket也接连注册到Selector
         */
        while(true){
            int num = selector.select();                        //获取通道内是否有选择器的关心事件
            if(num<1){continue; }
            Set selectedKeys = selector.selectedKeys();         //获取通道内关心事件的集合
            Iterator it = selectedKeys.iterator();
            while (it.hasNext()) {//遍历每个事件
                try{
                    SelectionKey key = (SelectionKey)it.next();

                    //有一个新联接接入事件,服务端事件
                    if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {

                        // 接收这个新连接
                        ServerSocketChannel serverChanel = (ServerSocketChannel)key.channel();

                        //从serverSocketChannel中创建出与客户端的连接socketChannel
                        SocketChannel sc = serverChanel.accept();
                        sc.configureBlocking( false );

                        // Add the new connection to the selector
                        // 把新连接注册到选择器
                        SelectionKey newKey = sc.register( selector, SelectionKey.OP_READ );
                        it.remove();

                        System.out.println( "Got connection from "+sc );

                    }else if((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ){//读客户端数据的事件,此时有客户端发数据过来,客户端事件

                        // 读取数据
                        SocketChannel sc = (SocketChannel)key.channel();
                        int bytesEchoed = 0;
                        while((bytesEchoed = sc.read(echoBuffer))> 0){
                            System.out.println("bytesEchoed:"+bytesEchoed);
                        }
                        echoBuffer.flip();
                        System.out.println("limit:"+echoBuffer.limit());

                        byte [] content = new byte[echoBuffer.limit()];

                        echoBuffer.get(content);

                        String request =new String(content);

                        this.doPost(request,sc);

                        echoBuffer.clear();
                        it.remove();

                     }
                }catch(Exception e){

                }
            }
        }
    }

    public void doPost(String request,SocketChannel sc){
        boolean isok=false;
        String response ="";
        int i = request.indexOf(" ");
        String order = request.substring(0, request.indexOf(" "));
        String data = request.substring(i+1, request.length());
        String[] items = data.split(",");
        Map <String,String> dataMap = new HashMap<String,String> ();
        for (String str:items){
            if(!str.isEmpty()&&!str.equals(" ")){
                String[] fieldAndValue = str.split(":");
                dataMap.put(fieldAndValue[0],fieldAndValue[1]);
            }

        }
        if (order.equals("add") && dataMap.size()>0){
            ContactsDaoApi daoApi = new Persistence();
            Contacts contact = new Contacts();
            Set<String> keys = dataMap.keySet();
            for (String key:keys) {
                String value = dataMap.get(key);
                if(key.equals("name")){
                    contact.setName(value);
                }
                if(key.equals("email")){
                    contact.setEmail(value);
                }
                if(key.equals("phone")){
                    contact.setPhoneNumber(value);
                }
                if (key.equals("resume")){
                    contact.setResume(value);
                }
            }
            System.out.println(dataMap.toString());
            ((Persistence) daoApi).save(contact);
        }else if(order.equals("find")){
            ContactsDaoApi daoApi = new Persistence();
            List<Contacts> contactList = new ArrayList<Contacts>();
            if(dataMap.size()== 0){
                contactList = daoApi.findAll();
            }else{
                Contacts contact =  new Contacts();
                Set<String> keys = dataMap.keySet();
                for (String key:keys) {
                    String value = dataMap.get(key);
                    if(key.equals("name")){
                        contact = daoApi.findByName(value);
                    }
                    if(key.equals("email")){
                        contact = daoApi.findByEmail(value);
                    }
                    if(key.equals("phone")){
                        contact  = daoApi.findByPhone(value);
                    }
                }
                contactList.add(contact);
            }
            if(contactList!=null && contactList.size()>0){
                StringBuffer stringBuffer= new StringBuffer();
                stringBuffer.append("<html><body>");
                for (Contacts contact :contactList){
                    stringBuffer.append(contact.toString());
                    stringBuffer.append("<br><br>");
                }
                stringBuffer.append("<body><html>");
                response = stringBuffer.toString();
            }else{
                response = "未找到符合该条件的用户，请悉知！";
            }
        }else{
            response = "操作命令暂不支持！";
        }
        handleResponse(sc, response);
    }

    
    private void handleResponse(SocketChannel sc, String result) {
        ByteBuffer bb = ByteBuffer.allocate( result.length() );
        bb.put(result.getBytes());
        bb.flip();
        try {
            sc.write(bb);
        } catch (IOException e) {
            e.printStackTrace();
        }
        bb.clear();
    }


    public static void main(String[] args) throws IOException {
        NioServer ns=new NioServer();
        ns.BuildNioServer();
    }
}
